﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Ex03.GarageLogic
{
    public class Vehicle
    {
        private String m_VehicleModelName;
        private String m_VehicleLicenseNumber;
        private float m_VehicleRemainingEnergyPercentage;
        private int m_VehicleWheelAmount;
        private List<Wheel> m_VehicleWheelList;
        private GarageManagment.eVehicleRepairState m_VehicleStatus;

        /// <summary>
        /// This is the c'tor for the base class "Vehicle", it checks for the legality of it's parameters :
        /// 1. "i_LicenseNumber" : that it's not a null value.
        /// 2. "i_NumberOfWheels" : that it's not a negative number.
        /// 3. "i_WheelMaxAirPressure" : that it's a positive number.
        /// </summary>
        /// <seealso cref="isWheelAmountLegal">
        /// This method does the legality check for the wheels amount.
        /// </seealso>
        /// <param name="i_LicenseNumber"></param>
        /// <param name="i_VehicleModelName"></param>
        /// <param name="i_NumberOfWheels"></param>
        /// <param name="i_WheelMaxAirPressure"></param>
        protected Vehicle(
            string i_VehicleModelName,
            string i_VehicleLicenseNumber,
            int i_VehicleWheelAmount,
            float i_VehicleWheelMaximumAirPressure)
        {
            if (i_VehicleLicenseNumber == null)
            {
                FormatException LicenseNumberError = new FormatException();

                throw LicenseNumberError;
            }
            else if (i_VehicleModelName == null)
            {
                FormatException ModelNameError = new FormatException();

                throw ModelNameError;
            }
            else if (!isWheelAmountLegal(i_VehicleWheelAmount))
            {
                ValueOutOfRangeException WheelAmountError = new ValueOutOfRangeException();

                throw WheelAmountError;
            }
            else if (!isMaximumWheelsAirPressureLegal(i_VehicleWheelMaximumAirPressure))
            {
                ValueOutOfRangeException WheelAirPressureError = new ValueOutOfRangeException();

                throw WheelAirPressureError;
            }
            else
            {
                m_VehicleLicenseNumber = i_VehicleLicenseNumber;
                m_VehicleModelName = i_VehicleModelName;
                m_VehicleWheelAmount = i_VehicleWheelAmount;
                m_VehicleWheelList = new List<Wheel>();
                for (int i = 0; i < m_VehicleWheelAmount; i++)
                {
                    m_VehicleWheelList.Add(new Wheel(i_VehicleWheelMaximumAirPressure));
                }
            }
        }

        /// <summary>
        /// This method checks that the wheels amount is legal (greater or equals to zero).
        /// </summary>
        /// <param name="i_NumberOfWheels">
        /// This is the amount of wheels to check if legal.
        /// </param>
        /// <returns>
        /// This method returns "false" if the wheels amount is illegal (negative), otherwise - it returns "true".
        /// </returns>
        private bool isWheelAmountLegal(int i_NumberOfWheels)
        {
            bool ReturnValue = false;

            if (i_NumberOfWheels >= 0)
            {
                ReturnValue = true;
            }

            return ReturnValue;
        }

        /// <summary>
        /// This method checks the legality for the maximum air pressure (A.P.) (a positive float).
        /// </summary>
        /// <param name="i_WheelMaxAirPressure">
        /// This is the value this method checks.
        /// </param>
        /// <returns>
        /// This method returns "false" if the A.P. value is illegal (negative or zero), otherwise - it returns "true".
        /// </returns>
        private bool isMaximumWheelsAirPressureLegal(float i_WheelMaxAirPressure)
        {
            bool ReturnValue = false;

            if (i_WheelMaxAirPressure > 0F)
            {
                ReturnValue = true;
            }

            return ReturnValue;
        }

        public string VehicleModelName
        {
            get { return m_VehicleModelName; }
            set 
            {
                if (value == null)
                {
                    ArgumentException VehicleModelNameError = new ArgumentException();

                    throw VehicleModelNameError;
                }
                else
                {
                    m_VehicleModelName = value;
                }
            }
        }

        public string VehicleLicenseNumber
        {
            get { return m_VehicleLicenseNumber; }
            set 
            {
                if (value == null)
                {
                    ArgumentException VehicleLicenseNumberError = new ArgumentException();

                    throw VehicleLicenseNumberError;
                }
                else
                {
                    m_VehicleLicenseNumber = value; 
                }
            }
        }

        public float VehicleRemainingEnergyPercentage
        {
            get { return m_VehicleRemainingEnergyPercentage; }
            set
            {
                if (isVehicleRemainingEnergyPercentageSettingLegal(value))
                {
                    m_VehicleRemainingEnergyPercentage = value;
                }
            }
        }

        private bool isVehicleRemainingEnergyPercentageSettingLegal(float i_NewEnergyLevelPercentage)
        {
            bool ReturnValue = false;

            if ((i_NewEnergyLevelPercentage >= 0F) && (i_NewEnergyLevelPercentage <= 100F))
            {
                ReturnValue = true;
            }
            else
            {
                ValueOutOfRangeException EnergySourceSettingError = new ValueOutOfRangeException();

                throw EnergySourceSettingError;
            }

            return ReturnValue;
        }

        virtual public bool AddPropulsionMaterial(
            EnergyType.eEnergyType i_PropulsionMaterialType, 
            float i_PropulsionMaterialAmountToAdd) 
        {
            throw new NotImplementedException();
        }

        public GarageManagment.eVehicleRepairState VehicleState
        {
            get { return m_VehicleStatus; }
            set 
            { 
                if (!isVehicleStateLegal(value))
                {
                    ArgumentException VehicleStateError = new ArgumentException();

                    throw VehicleStateError;
                }
                else
                {
                    m_VehicleStatus = value; 
                }
            }
        }

        public override bool Equals(object obj)
        {
            bool ReturnValue = false;

            if ((obj as Vehicle).VehicleLicenseNumber == this.VehicleLicenseNumber)
            {
                ReturnValue = true;
            }

            return ReturnValue;
        }

        public void InflateAllVehicleWheelsToMaximumAirPressure()
        {
            foreach (Wheel CurrentWheel in m_VehicleWheelList)
            {
                CurrentWheel.InflateWheel(CurrentWheel.WheelMaxAirPressureAllowed - CurrentWheel.WheelCurrentAirPressure);
            }
        }

        private bool isVehicleStateLegal(GarageManagment.eVehicleRepairState i_VehicleStateToCheck)
        {
            bool ReturnValue = false;

            switch (i_VehicleStateToCheck)
            {
                case GarageManagment.eVehicleRepairState.BillPaid:
                case GarageManagment.eVehicleRepairState.InRepair:
                case GarageManagment.eVehicleRepairState.Repaired:
                    ReturnValue = true;
                    break;
                case GarageManagment.eVehicleRepairState.DefaultValue:
                default:
                    break;
            }

            return ReturnValue;
        }

        // why do we need this method for ?
        public override int GetHashCode()
        {
            return this.VehicleLicenseNumber.GetHashCode();
        }

        //virtual List<String> CollectQustionsListToAskUser()
        //{
        //    List<String> qustionsList = new List<String>();

        //    qustionsList.Add(String.Format("Enter Model Name :"));
        //    qustionsList.Add(String.Format("Enter Owner Name :"));
        //    qustionsList.Add(String.Format("Enter Owner Phone Number :"));
        //  //  qustionsList.Add(String.Format("Enter Remaining Energy Percentage :"));
        //    foreach (Wheel wheel in m_WheelsOfVehicleList)
        //    {
        //        qustionsList.Add(String.Format("Enter Wheel Current Air Pressure:"));
        //        qustionsList.Add(String.Format("Enter Wheel Manufacturer Name:"));
        //    }
        //    return qustionsList;
        //}

        //public virtual void GetStringsFromUserAndUpdateVehicleData(List<String> i_Answers)
        //{
        //    ModelName = i_Answers[0];
        //    OwnerName = i_Answers[1];
        //    OwnerPhoneNumber = i_Answers[2];

        //    //m_RemainingEnergyPercentage = float.Parse(i_Answers[3]);
        //    //if (m_RemainingEnergyPercentage < 0 || m_RemainingEnergyPercentage > 100)
        //    //{
        //    //    throw new Exception("Remaining Energy Percentage Is InValid");
        //    //}
        //    i_Answers.RemoveRange(0, 3);
        //    foreach (Wheel wheel in m_WheelsOfVehicleList)
        //    {
        //        try
        //        {
        //            wheel.CurrentAirPressure = int.Parse(i_Answers[0]);
        //            wheel.Manufacturer = i_Answers[1];
        //            i_Answers.RemoveRange(0,2);

        //        }
        //        catch (FormatException ex)
        //        {
        //            throw new FormatException("Wheel Air Pressure Input In Wrong Format", ex);
        //        }
                 
        //    }
        //}

        //public virtual List<string> GetAllInformation()
        //{
        //    List<String> ReturnValue = new List<string>();

        //    ReturnValue.Add(String.Format("Vehclie License Number: {0}", LicenseNumber));
        //    ReturnValue.Add(String.Format("Model Name: {0}",ModelName));
        //    ReturnValue.Add(String.Format("Owner Name: {0}",OwnerName));
        //    ReturnValue.Add(String.Format("Owner Phone Number: {0}",OwnerPhoneNumber));
        //    ReturnValue.Add(String.Format("Remaining Energy Percentage: {0}",RemainingEnergyPercentage));
        //    ReturnValue.Add(String.Format("Vehicle State: {0}",VehicleState));
        //    foreach (Wheel Wheel in m_WheelsOfVehicleList)
        //    {
        //        ReturnValue.Add(String.Format("Wheel Air Pressure: {0}", Wheel.CurrentAirPressure));
        //        ReturnValue.Add(String.Format("Wheel Manufacturer Name: {0}", Wheel.Manufacturer));
        //    }

        //    return ReturnValue;
        //}
    }
}
